Skip to content

feat(connectors): add OAuth connector resource schemas and file parsing#189

Open
Paveltarno wants to merge 3 commits intomainfrom
pavelta-connectors-1
Open

feat(connectors): add OAuth connector resource schemas and file parsing#189
Paveltarno wants to merge 3 commits intomainfrom
pavelta-connectors-1

Conversation

@Paveltarno
Copy link
Contributor

@Paveltarno Paveltarno commented Feb 4, 2026

Note

Description

This PR adds comprehensive OAuth connector support to the Base44 CLI, enabling users to manage OAuth integrations (Google services, Slack, Notion, etc.) through connectors/*.jsonc files. It implements the complete connector lifecycle including file parsing with Zod validation, API client for CRUD operations, OAuth authorization flow with browser redirect and polling, and a base44 connectors push command that syncs connectors and handles interactive authorization.

Related Issue

Closes #184

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Other (please describe):

Changes Made

  • Resource schemas (src/core/resources/connector/schema.ts): Defined Zod schemas for 12 OAuth providers (googlecalendar, googledrive, gmail, googlesheets, googledocs, googleslides, slack, notion, salesforce, hubspot, linkedin, tiktok) with discriminated union, JSDoc links to official OAuth documentation, and comprehensive API response schemas
  • File parsing (config.ts): Implemented readAllConnectors() with validation rules enforcing filename-type matching, duplicate detection, and graceful handling of missing directories
  • API client (api.ts): Added four connector management functions: listConnectors(), setConnector() (sync), getOAuthStatus() (poll), and removeConnector()
  • Push logic (push.ts): Created pushConnectors() that syncs local connectors and removes upstream-only connectors, returning detailed results per connector
  • OAuth flow (oauth.ts): Implemented runOAuthFlow() that opens browser, polls status with 5-minute timeout using p-wait-for, and returns final status
  • CLI command (src/cli/commands/connectors/push.ts): Added base44 connectors push with interactive OAuth authorization, summary reporting, and CI mode support
  • Testing: Added 523 lines of tests across unit tests (401 lines for core logic) and integration tests (122 lines for CLI), with 6 test fixtures covering valid, invalid, and edge cases
  • Project integration: Registered connector resource in project config, added to ProjectData type, and updated program to include connectors command

Testing

  • I have tested these changes locally
  • I have added/updated tests as needed
  • All tests pass (npm test)

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (if applicable)
  • My changes generate no new warnings
  • I have updated CLAUDE.md/AGENTS.md if I made architectural changes (follows existing Resource pattern)

Additional Notes

This implementation follows the established Resource pattern used for entities and functions. The OAuth flow includes intelligent handling of edge cases:

  • Already authorized connectors skip OAuth flow
  • Different user conflicts are reported as errors with user email
  • CI environment automatically skips interactive authorization
  • 5-minute timeout for OAuth polling with clear user feedback
  • Comprehensive summary reporting showing synced, added, removed, and failed connectors

The connector resource integrates seamlessly with existing project management (readProjectConfig) and follows all architectural patterns from CLAUDE.md including error handling, structured errors, API client patterns, and dependency injection via CLIContext.

Note: Typecheck CI is currently failing - needs investigation before merge.


🤖 Generated by Claude | 2026-02-08 23:47 UTC

@github-actions
Copy link
Contributor

github-actions bot commented Feb 4, 2026

🚀 Package Preview Available!


Install this PR's preview build with npm:

npm i @base44-preview/cli@0.0.28-pr.189.322a27a

Prefer not to change any import paths? Install using npm alias so your code still imports base44:

npm i "base44@npm:@base44-preview/cli@0.0.28-pr.189.322a27a"

Or add it to your package.json dependencies:

{
  "dependencies": {
    "base44": "npm:@base44-preview/cli@0.0.28-pr.189.322a27a"
  }
}

Preview published to npm registry — try new features instantly!

@kfirstri kfirstri moved this from Backlog to In progress in CLI Development Feb 5, 2026
Paveltarno and others added 3 commits February 8, 2026 17:53
Add connector resource module supporting 12 OAuth providers:
googlecalendar, googledrive, gmail, googlesheets, googledocs,
googleslides, slack, notion, salesforce, hubspot, linkedin, tiktok.

- Zod discriminated union schema with type discriminator per provider
- JSDoc links to official OAuth scope documentation for each provider
- JSONC file reading with validation (filename must match type field)
- API response schemas for upstream connector state
- Unit tests with fixtures for valid, invalid, and mismatched connectors

Part of: #184

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add API client methods for OAuth connector operations:
- listConnectors: list all connectors for current app
- syncConnector: sync connector with exact scope matching
- getOAuthStatus: poll OAuth authorization status
- removeConnector: remove a connector integration

Also update response schemas and clean up verbose comments.

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* feat(connectors): implement push logic for syncing connectors

Add pushConnectors function that:
- Syncs all local connectors via /sync endpoint
- Removes upstream-only connectors not in local config
- Returns typed results (synced, removed, needs_oauth, error)

Includes unit tests covering all scenarios.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(connectors): add OAuth flow handling with browser redirect and polling (#192)

* feat(connectors): add OAuth flow handling with browser redirect and polling

Add runOAuthFlow function that:
- Opens OAuth redirect URL in browser
- Polls getOAuthStatus until ACTIVE or FAILED
- Returns PENDING on timeout (5 minutes)

Uses p-wait-for TimeoutError for robust timeout detection.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* connectors: base44 connectors push (#194)

* final connector work sofi 1

* scopes

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
@Paveltarno Paveltarno force-pushed the pavelta-connectors-1 branch from c3543de to c1bb2d1 Compare February 8, 2026 15:53
@claude
Copy link

claude bot commented Feb 8, 2026

Code Review

I found 4 issues that need to be addressed:


1. 🔴 Case mismatch in ConnectorStatusSchema - Will cause runtime failures

File: src/core/resources/connector/schema.ts (line 109-113)

The schema defines lowercase enum values:

export const ConnectorStatusSchema = z.enum([
  "active",
  "disconnected",
  "expired",
]);

However, the API returns uppercase values based on:

Impact: When listConnectors() validates API responses, Zod will throw SchemaValidationError for any uppercase status values, making connectors push fail whenever upstream connectors exist.

Fix: Change to uppercase to match the API:

export const ConnectorStatusSchema = z.enum([
  "ACTIVE",
  "DISCONNECTED",
  "EXPIRED",
]);

2. 🟡 Potential "Already connected by null" error message

File: src/core/resources/connector/push.ts (line 69-72)

When error === "different_user", the code constructs an error message:

error:
  response.error_message ||
  `Already connected by ${response.other_user_email}`,

Both error_message and other_user_email are nullable per the schema definition (z.string().nullable().optional()). If both are null:

  1. The || operator treats null as falsy → falls through
  2. Template literal interpolates null as string "null"
  3. User sees: "Already connected by null"

Fix: Add null check with meaningful fallback:

error:
  response.error_message ||
  (response.other_user_email
    ? `Already connected by ${response.other_user_email}`
    : "Already connected by another user"),

3. 🔵 Direct chalk usage instead of centralized theme utility

File: src/cli/commands/connectors/push.ts (line 2 and throughout)

The file imports and uses chalk directly:

import chalk from "chalk";
// Used on lines 56, 59, 62, 65, 68, 106, 110
log.info(chalk.bold("Summary:"));
log.info(chalk.green(`  Synced: ...`));

CLAUDE.md Rule (line 669):

Use theme for styling - Never use chalk directly in commands; import theme from utils and use semantic color/style names

Why this matters: All other CLI commands use the centralized theme for consistent styling.

Fix: Replace with theme utility:

import { theme } from "@/cli/utils/index.js";

// Then replace usages:
theme.styles.bold("text")           // instead of chalk.bold()
theme.colors.base44Orange("text")   // instead of chalk.green()/red()/yellow()
theme.styles.dim("text")            // instead of chalk.dim()

4. 🔵 Bare Error throw instead of structured error class

File: src/core/resources/connector/config.ts (line 48)

The code throws a generic error:

throw new Error(`Duplicate connector type "${connector.type}"`);

CLAUDE.md Rule (line 672):

Use structured errors - Never throw new Error(); use specific error classes from @/core/errors.js with appropriate hints

Why this matters: Bare Error lacks:

  • Proper error codes for telemetry
  • User-facing hints for resolution
  • isUserError classification

Fix: Use InvalidInputError with hints:

import { InvalidInputError } from "@/core/errors.js";

// Replace the throw with:
throw new InvalidInputError(
  `Duplicate connector type "${connector.type}"`,
  {
    hints: [
      { message: "Each connector type can only be defined once" },
      { message: "Check your connectors directory for duplicate files" },
    ],
  }
);

Summary

  • 1 critical bug (case mismatch) will cause runtime failures
  • 1 logic bug (null interpolation) produces confusing error messages
  • 2 convention violations (chalk usage, error handling) for consistency with codebase standards

All other aspects of the implementation follow established patterns correctly (Resource interface, Zod validation, API error handling, testing structure, command factory pattern).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

Add OAuth connectors as a CLI resource

1 participant